// ExamplePlugin.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "ExamplePlugin.h"
#include "..\Shared\ObjectManager.h"

__declspec(dllexport) IPlugin* __stdcall CreateInstance() // needed for pluginmanager
{
	return (IPlugin*)new ExamplePlugin(); // returns a newly created instance of the ExamplePlugin
}

__declspec(dllexport) int __stdcall GetInterfaceVersion(void) // Needed for pluginmanager
{
	return PluginInterfaceVersion; // returns the Plugin Interface Version. 
}

ExamplePlugin::ExamplePlugin()
{
	m_ModuleInfo.pluginName = "ExamplePlugin"; // Change to the name of your plugin
	m_ModuleInfo.author = "Josh Anderson"; // Change to your name
	m_ModuleInfo.version = 0x01000000; // 0xMMmmaabb   MM = Major mm = Minor aa = Macro bb = Build
	m_ModuleInfo.numOfCommands = 2; // Needs to equal the number of commands that your plugin handles.
	m_ModuleInfo.commands[0] = "Printf"; // Each of these is the name of the command.
	m_ModuleInfo.commands[1] = "PrintObject";
}

bool __stdcall ExamplePlugin::HandleCommand(Command &NewCommand)
{
	bool Found = false;
	for(int i = 0; i < m_ModuleInfo.numOfCommands; i++) // Checking all handled commands against the supply command
	{
		if(m_ModuleInfo.commands[i] == NewCommand.name) // If a match of names we have found and break out of the loop
		{
			Found = true;
			break;
		}
	}
	if(!Found) // if not found return false to the plugin manager for this command.
		return false;
	if(NewCommand.name == "Printf") // Here is handle the Printf command
	{
		char Format[1024];
		memset(Format, 0 , 1024);
		for(int i = 0; i < NewCommand.Arguments.Size(); i++)
		{
			switch(NewCommand.Arguments[i].GetType()) // checks the type of the values in the arguments and prints them accordly
			{
			case AT_INT:
				sprintf_s(Format, 1024, "%s%d", Format, NewCommand.Arguments[i].ToInt());
				break;
			case AT_FLOAT:
				sprintf_s(Format, 1024, "%s%f", Format, NewCommand.Arguments[i].ToFloat());
				break;
			case AT_STRING:
				sprintf_s(Format, 1024, "%s%s", Format, NewCommand.Arguments[i].ToCharPtr());
				break;
			case AT_UNKNOWN:
				NewCommand.Returns.Add(Value("Error","Passed Value Type is unknown"));
				break;
			};
		}
		printf(Format); // prints the formated string.
		NewCommand.Arguments.Clear(); // clear memory of the arguments because they are no longer needed.
		NewCommand.Returns.Add("Printed"); // Add a value to the returns list stating it printed. Will be the only value if no errors occored
		return true; // returns that the command was handled.
	}
	else if(NewCommand.name == "PrintObject") // Hanldes the command PrintObject
	{
#ifndef FORMATLEN
#define FORMATLEN 102400
#endif
		char Format[FORMATLEN]; //  a buffer to hold the formated string.
		memset(Format, 0, FORMATLEN); // sets it all to null
		for(int i = 0; i < NewCommand.Arguments.Size(); i++) // go through all of the supplied arguments.
		{
			if(m_Objects->GetBaseAttributeFromObject(NewCommand.Arguments[i],"Name") != "Error") // checks that the argument at i is a object in the object manager
			{
				sprintf_s(Format, FORMATLEN, "%s*New Object*\n", Format);
				for(int j = 0; j < m_Objects->GetNumberOfAttributesFromObject(NewCommand.Arguments[i]); j++) //gets the nubmer of attributes from the object. And loops through all of them
				{
					Value TempAttribute;
					TempAttribute = m_Objects->GetBaseAttributeFromObject(NewCommand.Arguments[i], j); //Gets the jth argument from the object
					// Attribute.name is a char array
					// Attribute.ToCharPtr() returns a const char array. formats ints and floats to char arrays
					// Attribute.GetTypeString() returns a Value of type string that holds a string that states the type of the value it was called from
					sprintf_s(Format, FORMATLEN, "%s  %s: %s %s\n", Format, TempAttribute.name, TempAttribute.ToCharPtr(), TempAttribute.GetTypeString().ToCharPtr());
				}
				Effect TempEffect;
				for(int j = 0; j < m_Objects->GetNumberOfEffectsFromObject(NewCommand.Arguments[i]); j++) // loop through all of the effects on the object.
				{
					TempEffect = m_Objects->GetEffectFromObject(NewCommand.Arguments[i], j); //Grabs the jth effect on the object.
					sprintf_s(Format, FORMATLEN, "%s  Effect %s\n", Format, TempEffect.name); //Effect.name is a char array holding the name of the effect
					for(int k = 0; k < TempEffect.Attributes.Size(); k++) // loop through all of the attributes of the effect.
					{
						Value TempAttribute;
						TempAttribute = TempEffect.Attributes[k];
						sprintf_s(Format, FORMATLEN, "%s    %s: %s %s\n", Format, TempAttribute.name, TempAttribute.ToCharPtr(), TempAttribute.GetTypeString().ToCharPtr());
					}
				}
				Event TempEvent;
				for(int j = 0; j < m_Objects->GetNumberOfEventsFromObject(NewCommand.Arguments[i]); j++) // loop through all of the events of the object
				{
					TempEvent = m_Objects->GetEventFromObject(NewCommand.Arguments[i], j); // Gets the jth event of the object
					sprintf_s(Format, FORMATLEN, "%s  Event %s\n", Format, TempEvent.name);  // Event.name is a float
					for(int k = 0; k < TempEvent.Parameters.Size(); k++) // Loop through all of the parameters of the event
					{
						Value TempAttribute;
						TempAttribute = TempEvent.Parameters[k]; // Gets the kth parameter of the event
						sprintf_s(Format, FORMATLEN, "%s    %s: %s\n", Format, TempAttribute.name, TempAttribute.GetTypeString().ToCharPtr());
					}
				}
				if((*m_Objects)[NewCommand.Arguments[i]].Parent) // check if object has a parent
					// If has parent put the "Name" of the object in the string
					sprintf_s(Format, FORMATLEN, "%s  Parent: %s\n", Format, (*m_Objects)[NewCommand.Arguments[i]].Parent->GetBaseAttribute("Name").ToCharPtr());
				else
					// else put NULL
					sprintf_s(Format, FORMATLEN, "%s  Parent: NULL\n", Format);
				for(int j = 0; j < m_Objects->GetNumberOfChildrenFromObject(NewCommand.Arguments[i]); j++) //loop through all of the children of the object
				{
					//Just print the "Name" of each child.
					sprintf_s(Format, FORMATLEN, "%s    Child: %s\n", Format, (*m_Objects)[NewCommand.Arguments[i]][j].GetBaseAttribute("Name").ToCharPtr());
				}
			}
		}
		printf(Format); // Print the Format string.
		NewCommand.Returns.Add(Value("Result",1));
		return true;
	}
	return false;
}